home *** CD-ROM | disk | FTP | other *** search
- /*
- * SFtoSpr - Star Fighter 3000 graphics converter
- * Utility functions
- * Copyright (C) 2000 Chris Bazley
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public Licence as published by
- * the Free Software Foundation; either version 2 of the Licence, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public Licence
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- /* ANSI library files */
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdbool.h>
-
- /* RISC OS library files */
- #include "kernel.h"
- #include "toolbox.h"
- #include "event.h"
- #include "window.h"
- #include "wimplib.h"
- #include "gadgets.h"
- #include "swis.h"
- #include "saveas.h"
- #include "flex.h"
-
- /* My library files */
- #include "err.h"
- #include "msgtrans.h"
- #include "hourglass.h"
- #include "Macros.h"
- #include "Loader.h"
- #include "SFformats.h"
- #include "SprFormats.h"
- #include "NoBudge.h"
- #include "FilePerc.h"
-
- /* Local headers */
- #include "SFgfxconv.h"
- #include "Main.h"
- #include "Utils.h"
-
- /* ----------------------------------------------------------------------- */
- /* Function prototypes */
-
- static bool _check_anims_limits(char *anims_array, int last_tilenum);
-
- /* ----------------------------------------------------------------------- */
- /* Public functions */
-
- _kernel_oserror *open_above_iconbar(unsigned int flags, ObjectId id, ObjectId parent, ComponentId parent_component)
- {
- /* Open window horizontally centred on pointer, above iconbar */
- WimpGetPointerInfoBlock pointerinfo;
- WindowShowObjectBlock showblock;
- WimpGetWindowStateBlock winstate;
- ObjectId win_id;
-
- THROW(wimp_get_pointer_info(&pointerinfo))
- THROW(saveas_get_window_id(0, id, &win_id))
- THROW(window_get_wimp_handle(0, win_id, &(winstate.window_handle)))
- THROW(wimp_get_window_state(&winstate))
-
- showblock.visible_area.xmin = pointerinfo.x - (winstate.visible_area.xmax - winstate.visible_area.xmin)/2;
- showblock.visible_area.ymin = 96 + (winstate.visible_area.ymax - winstate.visible_area.ymin);
- return toolbox_show_object(flags, id, Toolbox_ShowObject_TopLeft, &showblock, parent, parent_component);
- }
-
- /*
- * File loading routines
- */
-
- _kernel_oserror *load_compressed(char *filepath, flex_ptr buffer_anchor)
- {
- return perc_operation(FILEPERC_OP_DECOMP, filepath, 0, buffer_anchor);
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *load_sprites(char *filepath, flex_ptr buffer_anchor)
- {
- return perc_operation(FILEPERC_OP_LOAD, filepath, 1u<<31, buffer_anchor);
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *load_animations(char *file_path, flex_ptr buffer)
- {
- /* A LoaderFileHandler for use with Loader component
- - Allocate buffer and load animations textfile given direct path */
- _kernel_oserror *err;
-
- /* Allocate flex buffer for data */
- if(!flex_alloc(buffer, sizeof(SF_MapTilesSetHdr))) {
- WRITE_GERR(shared_err_block, "NoMem");
- return &shared_err_block;
- }
-
- /* Read animations directly into our buffer */
- err = load_animsfilepath(file_path, (SF_MapTilesSetHdr **)buffer, true);
- if(err != NULL)
- flex_free(buffer);
-
- return err;
- }
-
- /*
- * File saving routines
- */
-
- _kernel_oserror *save_animsfile(char *filepath, SF_MapTilesSetHdr *putanimations)
- {
- /* Write textfile with animations */
- _kernel_last_oserror(); /* reset SCL's error recording */
-
- FILE *animdata = fopen(filepath, "w");
- if(animdata == NULL) {
- THROW(_kernel_last_oserror()) /* any OS error? */
- WRITE_ERR_SUB1(shared_err_block, "OpenOutFail", filepath);
- return &shared_err_block; /* failure */
- }
- int num_outputs = fprintf(animdata, "splash1:%d,%d,%d,%d\n",
- putanimations->splash_anim_1[0],
- putanimations->splash_anim_1[1],
- putanimations->splash_anim_1[2],
- putanimations->splash_anim_1[3]);
- if(num_outputs < 0)
- goto WriteFail;
-
- num_outputs = fprintf(animdata, "splash2:%d,%d,%d,%d\n",
- putanimations->splash_anim_2[0],
- putanimations->splash_anim_2[1],
- putanimations->splash_anim_2[2],
- putanimations->splash_anim_2[3]);
- if(num_outputs < 0)
- goto WriteFail;
-
- num_outputs = fprintf(animdata,"s2triggers:%d,%d,%d,%d\n",
- putanimations->splash_2_triggers[0],
- putanimations->splash_2_triggers[1],
- putanimations->splash_2_triggers[2],
- putanimations->splash_2_triggers[3]);
- if(num_outputs < 0)
- goto WriteFail;
-
- fclose(animdata);
- return NULL; /* success */
-
- WriteFail:
- fclose(animdata);
- THROW(_kernel_last_oserror()) /* any OS error? */
- WRITE_ERR_SUB1(shared_err_block, "WriteFail", filepath);
- return &shared_err_block; /* failure */
- }
-
- /*
- * General utility functions
- */
-
- char *copystring(char *string)
- {
- /* copy string into newly allocated memory */
- char *ptr;
-
- ptr = malloc(strlen(string)+1);
- if(ptr == NULL)
- err_complain(255,msgs_global("NoMem"));
- else
- strcpy(ptr, string);
- return ptr;
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *showgadget(ObjectId window, ComponentId gadget)
- {
- int height;
- BBox pos;
- THROW(gadget_get_bbox(0, window, gadget, &pos))
- if(pos.ymin < 0) /* already shown */
- return NULL;
- /* shift the icon into the window to show the button */
- height = pos.ymax - pos.ymin;
- pos.ymin = -pos.ymin; /* implicitly preserves dist. icbottom-to-wintop */
- pos.ymax = pos.ymin+height; /* keep dist. icbottom-to-ictop */
- return gadget_move_gadget(0, window, gadget, &pos);
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *hidegadget(ObjectId window, ComponentId gadget)
- {
- int height;
- BBox pos;
- THROW(gadget_get_bbox(0, window, gadget, &pos))
- if(pos.ymin > 0) /* already hidden */
- return NULL;
- /* shift the icon off the top to show the button */
- height = pos.ymax - pos.ymin;
- pos.ymin = -pos.ymin; /* implicitly preserves dist. icbottom-to-wintop */
- pos.ymax = pos.ymin+height; /* keep dist. icbottom-to-ictop */
- return gadget_move_gadget(0, window, gadget, &pos);
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *set_gadget_faded(bool fade, ObjectId id, ComponentId gad)
- {
- unsigned int flags_settings;
-
- THROW(gadget_get_flags(0, id, gad, &flags_settings))
- if(fade) {
- if(FLAG_SET(flags_settings, Gadget_Faded))
- return NULL;
- flags_settings |= Gadget_Faded;
- }
- else {
- if(!FLAG_SET(flags_settings, Gadget_Faded))
- return NULL;
- flags_settings &= (~Gadget_Faded);
- }
- return gadget_set_flags(0, id, gad, flags_settings);
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *getscreencentre(int *centreX,int *centreY)
- {
- /* Get screen centre */
- int XWindLimit,YWindLimit;
- int XEigFactor,YEigFactor;
- _kernel_swi_regs regs;
-
- regs.r[0]=-1; /* current mode */
- regs.r[1]=11; /* no of x pixels on screen-1 */
- THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
- XWindLimit=regs.r[2];
-
- regs.r[0]=-1; /* current mode */
- regs.r[1]=12; /* no of y pixels on screen-1 */
- THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
- YWindLimit=regs.r[2];
-
- regs.r[0]=-1; /* current mode */
- regs.r[1]=4; /* X eigen factor */
- THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
- XEigFactor=regs.r[2];
-
- regs.r[0]=-1; /* current mode */
- regs.r[1]=5; /* Y eigen factor */
- THROW(_kernel_swi(OS_ReadModeVariable,®s,®s))
- YEigFactor=regs.r[2];
-
- *centreX = (XWindLimit<<XEigFactor)/2;
- *centreY = (YWindLimit<<YEigFactor)/2;
- return NULL;
- }
-
- /* ----------------------------------------------------------------------- */
-
- char *tail(char *pathname, int length)
- {
- char *ptr;
- int dotcount;
-
- ptr = (char *)((int)pathname + strlen(pathname)); /* terminator */
- dotcount = 0;
- while(ptr > pathname && dotcount<length) {
- ptr--; /* scan string backwards from terminator */
- if(*ptr == '.')
- dotcount++;
- }
- if(dotcount >= length)
- return (char *)((int)ptr + 1);
- return ptr;
- }
-
- /*
- * Check header of tiles set for valid animations data
- */
-
- bool check_animations(SF_MapTilesSetHdr **hdr)
- {
- /* Check that the tile numbers are valid */
- if(!_check_anims_limits((*hdr)->splash_anim_1, (*hdr)->lasttile_num)
- || !_check_anims_limits((*hdr)->splash_anim_2, (*hdr)->lasttile_num)) {
- if(!dialogue_confirm(msgs_lookup("DuffAnimsBnd")))
- return false;
- }
-
- /* Friendly check that the splash triggers cover the splash animation */
- bool covered, one_not_covered = false;
- bool anims_eq = true;
- for(int a = 0; a < 4; a++) {
- covered = false;
- /* Check that one of the triggers covers this splash tile... */
- for(int b = 0; b < 4 && !covered; b++) {
- if((*hdr)->splash_2_triggers[b] == (*hdr)->splash_anim_2[a]
- || ((*hdr)->splash_2_triggers[b]+1) == (*hdr)->splash_anim_2[a])
- covered = true;
- }
- if(!covered)
- one_not_covered = true;
- if((*hdr)->splash_anim_1[a] != (*hdr)->splash_anim_2[a])
- anims_eq = false;
- }
-
- if(one_not_covered && !anims_eq) {
- if(!dialogue_confirm(msgs_lookup("Splash2Warn")))
- return false;
- }
- return true;
- }
-
- /*
- * Check sprite areas for potential tile/planet graphics
- */
-
- bool contains_valid_planets(spriteareaheader **sa)
- {
- int numsprites = (*sa)->sprite_count;
-
- nobudge_register(1024);
- spriteheader *sph = (spriteheader *)((int)(*sa) + (*sa)->first);
-
- hourglass_on();
- for(int sprite = 0; sprite < numsprites; sprite++) {
-
- /* Check sprite header */
- char spritename[13];
- strncpy(spritename, sph->name, sizeof(spritename)-1);
- if(spritehdr_validpla(sph, spritename) >= 0) {
- hourglass_off();
- nobudge_deregister();
- return true; /* found */
- }
- sph = (spriteheader *)((int)sph+sph->size);
- }
- hourglass_off();
-
- nobudge_deregister();
- return false; /* no valid planets in sprite area */
- }
-
- /* ----------------------------------------------------------------------- */
-
- bool contains_valid_tiles(spriteareaheader **sa)
- {
- int numsprites = (*sa)->sprite_count;
-
- nobudge_register(1024);
- spriteheader *sph = (spriteheader *)((int)(*sa) + (*sa)->first);
-
- hourglass_on();
- for(int sprite = 0; sprite < numsprites; sprite++) {
-
- /* Check sprite header */
- char spritename[13];
- strncpy(spritename, sph->name, sizeof(spritename)-1);
- if(spritehdr_validtile(sph, spritename) >= 0) {
- hourglass_off();
- nobudge_deregister();
- return true; /* found */
- }
-
- sph = (spriteheader *)((int)sph + sph->size);
- }
- hourglass_off();
-
- nobudge_deregister();
- return false; /* no valid tiles in sprite area */
- }
-
- /* ----------------------------------------------------------------------- */
-
- bool dialogue_confirm(const char *mess)
- {
- strncpy(shared_err_block.errmess, mess, sizeof(shared_err_block.errmess)-1);
-
- if(wimp_version >= 321) {
- /* Nice error box */
- return (wimp_report_error(&shared_err_block, (1u << 8)|(1u << 11), taskname, NULL, NULL, msgs_lookup("ConButtons")) == 3);
- }
- else {
- /* Backwards compatibility */
- return (wimp_report_error(&shared_err_block, Wimp_ReportError_OK|Wimp_ReportError_Cancel, taskname) == Wimp_ReportError_OK);
- }
- }
-
- /* ----------------------------------------------------------------------- */
-
- int delete_object_handler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
- {
- /* Generic handler for deleting an object */
- RE(toolbox_delete_object(0, id_block->self_id))
-
- return 1; /* claim event */
- }
-
- /* ----------------------------------------------------------------------- */
- /* Private functions */
-
- static bool _check_anims_limits(char *anims_array, int last_tilenum)
- {
- for(int i = 0; i < 4; i++) {
- if((anims_array[i] > last_tilenum && anims_array[i] != 255)
- || anims_array[i] < 0)
- return false;
- }
- return true;
- }
-
- /* ----------------------------------------------------------------------- */
-
- _kernel_oserror *load_animsfilepath(char *filepath, SF_MapTilesSetHdr **getanimations, bool err_if_absent)
- {
- /* Load animations textfile given explicit filepath */
- int a, b ,c, d, numread;
-
- nobudge_register(256); /* remove a layer of indirection */
- SF_MapTilesSetHdr *anims_ptr = *getanimations;
-
- FILE *animdata = fopen(filepath, "r");
- if(animdata != NULL) {
- /* Read values from textfile (these may be overwritten subsequently by text from dialogue box) */
- numread = fscanf(animdata, "splash1:%d,%d,%d,%d\n", &a, &b, &c, &d);
- if(numread == EOF || numread<4 || a>255 || b>255 || c>255 || d>255) {
- fclose(animdata);
- WRITE_ERR(shared_err_block, "BadAnimsFile");
- return &shared_err_block; /* failure */
- }
- anims_ptr->splash_anim_1[0] = a;
- anims_ptr->splash_anim_1[1] = b;
- anims_ptr->splash_anim_1[2] = c;
- anims_ptr->splash_anim_1[3] = d;
-
- numread = fscanf(animdata, "splash2:%d,%d,%d,%d\n", &a, &b, &c, &d);
- if(numread == EOF || numread<4 || a>255 || b>255 || c>255 || d>255) {
- fclose(animdata);
- WRITE_ERR(shared_err_block, "BadAnimsFile");
- return &shared_err_block; /* failure */
- }
- anims_ptr->splash_anim_2[0] = a;
- anims_ptr->splash_anim_2[1] = b;
- anims_ptr->splash_anim_2[2] = c;
- anims_ptr->splash_anim_2[3] = d;
-
- numread = fscanf(animdata, "s2triggers:%d,%d,%d,%d\n", &a, &b, &c, &d);
- if(numread == EOF || numread<4 || a>255 || b>255 || c>255 || d>255) {
- fclose(animdata);
- WRITE_ERR(shared_err_block, "BadAnimsFile");
- return &shared_err_block; /* failure */
- }
- anims_ptr->splash_2_triggers[0] = a;
- anims_ptr->splash_2_triggers[1] = b;
- anims_ptr->splash_2_triggers[2] = c;
- anims_ptr->splash_2_triggers[3] = d;
-
- fclose(animdata);
- }
- else {
- /* Blank data, then */
- memset(&(anims_ptr->splash_anim_1), 0, sizeof(&(anims_ptr)->splash_anim_1));
- memset(&(anims_ptr->splash_anim_2), 0, sizeof(&(anims_ptr)->splash_anim_2));
- memset(&(anims_ptr->splash_2_triggers), 0, sizeof(&(anims_ptr)->splash_2_triggers));
- if(err_if_absent) {
- WRITE_ERR(shared_err_block, "NoAnimFile");
- return &shared_err_block; /* failure */
- }
- }
- nobudge_deregister();
- return NULL; /* success */
- }
-